package com.jweb.framework.core.impl;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jweb.framework.core.Context;
import com.jweb.framework.core.CoreException;
import com.jweb.framework.core.Processing;
import com.jweb.framework.core.User;
import com.jweb.framework.core.channel.ChannelContext;
import com.jweb.framework.core.service.ServiceRegistry;

/** 
 * @author Thomas: 
 * ��˵�� ��Ĭ����������
 */
public class DefaultContext implements Context , Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7087179239467185774L;
	
	private static final Logger logger = LoggerFactory.getLogger(DefaultContext.class);
	
	private String requestId ;
	private String sessionId ;
	private String processId ;
	private long timeStamp ;
	private Locale locale ;
	private String state ;
	private CoreException coreException ;
	private HashMap dataMap = new HashMap(7);
	private HashMap attributes = new HashMap(3);
	private HashMap sessionAttributes = new HashMap(3);
	private transient HashMap variables = new HashMap(3);
	private transient ServiceRegistry serviceRegistry ;
	private transient Processing processing ;
	private boolean flag ;
	
	private User user ;  //
	private String msgType ;
	private String rspCode ;
	private String rspMsg ;
	
	private ChannelContext channelContext ;
	
	public DefaultContext(){
		this.timeStamp = System.currentTimeMillis();
		this.state = "";
		this.locale = Locale.getDefault();
	}
	
	public <T> T getAttribute(String name){
		return (T) this.attributes.get(name);
	}
	
	public Map<String , Object> getAttributes(){
		return Collections.unmodifiableMap(this.attributes);
	}
	
	public <T> T getData(String key){
		return (T) this.dataMap.get(key);
	}
	
	public Map<String , Object> getDataMap(){
		return new HashMap(this.dataMap);
	}
	
	public Map<String , Object> getDataMapDirectly(){
		return this.dataMap ;
	}
	
	public CoreException getException(){
		return this.coreException ;
	}
	
	public Locale getLocale(){
		return this.locale; 
	}
	
	public Processing getProcess(){
		return this.processing ;
	}
	
	public String getProcessId(){
		return this.processId ;
	}
	
	public String getRequestId(){
		return this.requestId ;
	}
	
	public <S> S getService(Class<S> clazz){
		if(this.serviceRegistry == null){
			return null ;
		}
		return this.serviceRegistry.findService(clazz);
	}
	
	public <S> S getService(String name){
		if(this.serviceRegistry == null){
			return null ;
		}
		return this.serviceRegistry.findService(name);
	}
	
	public <T> T getSessionAttribute(String key){
		return (T)this.sessionAttributes.get(key);
	}
	
	public Map<String , Object> getSessionAttributes(){
		return Collections.unmodifiableMap(this.sessionAttributes);
	}
	
	public String getSessionId(){
		return this.sessionId ;
	}
	
	public String getState(){
		return this.state;
	}
	
	public long getTimestamp(){
		return this.timeStamp;
	}
	
	public <T> T getVariable(String key){
		return (T) this.variables.get(key);
	}
	
	public Map<String , Object> getVariables(){
		return this.variables ;
	}
	
	public void setData(String key , Object val){
		this.dataMap.put(key , val);
	}
	
	public void setException(CoreException ce){
		this.coreException = ce ;
	}
	
	public void setLocale(Locale locale){
		this.locale = locale ;
	}
	
	public void setProcess(Processing processing){
		this.processing = processing ;
	}
	
	public void setProcessId(String processId){
		this.processId = processId ;
	}
	
	public void setState(String state){
		this.state = state ;
	}
	
	public void setVariable(String key , Object val){
		this.variables.put(key , val);
	}
	
	public void setVariables(Map<String , Object> map){
		this.variables.putAll(map);
	}
	
	public void setAttribute(String key , Object val){
		if(this.flag){
			this.attributes.put(key , val);
		}
		else if(this.attributes.containsKey(key)){
			logger.warn("duplicated key in requestMap:{}, new value will skiped " , key);
		}
		else {
			this.attributes.put(key , val);
		}
	}
	
	public void setRequestId(String requestId){
		this.requestId = requestId ;
	}
	
	public void setSessionAttribute(String key , Object val){
		if(this.flag){
			this.sessionAttributes.put(key , val);
		}
		else if(this.sessionAttributes.containsKey(key)){
			logger.warn("duplicated key in sessionMap:{} , new value will skiped " , key);
		}
		else {
			this.sessionAttributes.put(key , val);
		}
	}
	
	public void setSessionId(String sessionId){
		this.sessionId = sessionId ;
	}
	
	public void setServiceRegistry(ServiceRegistry serviceRegistry){
		this.serviceRegistry = serviceRegistry ;
	}
	
	public void setDataMap(Map<String , Object> map){
		this.dataMap.putAll(map);
	}
	
	public <T extends User> T getUser() {
		
		return (T) this.user;
	}
	
	public void setUser(User user) {

		this.user = user;
	}
	
	public void clearContext(){
		this.dataMap.clear() ;
	}
	
	public void setMsgType(String msgType) {
		this.msgType = msgType ;
	}
	
	public void setRspCode(String rspCode) {
		this.rspCode = rspCode ;
	}
	
	public void setRspMsg(String rspMsg) {
		this.rspMsg = rspMsg ;
	}
	
	public String getMsgType() {
		return this.msgType ;
	}
	
	public String getRspCode() {
		return this.rspCode ;
	}
	
	public String getRspMsg() {
		return this.rspMsg ;
	}

	public ChannelContext getChannelContext() {
		return this.channelContext ;
	}

	public void setChannelContext(ChannelContext channelContext) {
		this.channelContext = channelContext ;
	}

	public Object removeData(String key) {
		return this.dataMap.remove(key);
	}

}
